package com.hh.myfish.aspect;

import com.hh.myfish.model.Fish;
import com.hh.myfish.model.FishStatus;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.stereotype.Component;

import java.util.HashMap;
import java.util.Map;
import java.util.Random;

@Component
@Aspect
public class FishAspect {
    // 切入点表达式
//    public static final String POINT_CUT = "execution(* com.hh.myfish.controller.FishController.doRpc(..))";

    // 因为一个消费者可以去调用多个提供者 每个提供者都有自己的断路器
    // 在消费者里面去创建一个断路器的容器集合
    // 断路器的容器
    public static Map<String, Fish> fishMap = new HashMap<>();

    Random random = new Random();

    static {
        // 假设 是 需要去调用order-service的服务
        fishMap.put("order-service", new Fish());
    }

    /**
     * 这个就类比拦截器
     * 就是要判断当前断路器的状态 从而决定是否发起调用（执行目标方法）
     * @param joinPoint
     * @return
     */
    @Around(value = "@annotation(com.hh.myfish.anno.MyFish)")
    public Object fishAroundR(ProceedingJoinPoint joinPoint) {
        // 这样写可以随便切
        Object result = null;
        // 获取到当前提供者的断路器
        Fish fish = fishMap.get("order-service");
        FishStatus status = fish.getStatus();
        // 三种状态
        switch (status) {
            // 正常 去调用 执行目标方法
            case CLOSE:
                try {
                    result = joinPoint.proceed();
                    return result;
                } catch (Throwable throwable) {
                    // 说明调用失败 记录次数 给当前fish
                    fish.addFailCount();
                    return "我是备胎";
                }
                // 不能调用
            case OPEN:
                return "我是备胎";
            // 可以用少许流量去调用
            case HALF_OPEN:
                int i = random.nextInt(5);
                System.out.println("i = " + i);
                if (i == 1) {
                    // 尝试调用
                    try {
                        result = joinPoint.proceed();
                        // 说明成功了 断路器关闭
                        fish.setStatus(FishStatus.CLOSE);
                        synchronized (fish.getLock()) {
                            // 唤醒线程
                            fish.getLock().notifyAll();
                        }
                        return result;
                    } catch (Throwable throwable) {
                        return "我是备胎";
                    }
                }
            default:
                return "我是备胎";
        }
    }
}
